using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace LINQ.Prep
{
    [TestClass]
    public class Presentation
    {
        [TestMethod]
        public void Demo1_some_definitions()
        {
            var basicArray = new int[0];
            var genericList = new List<int>();
            var genericDictionary = new Dictionary<int, string>();

            Assert.IsTrue(basicArray is IEnumerable);
            Assert.IsTrue(genericList is IEnumerable);
            Assert.IsTrue(genericDictionary is IEnumerable);

            // we're talking about anything that ultimately inherits from IEnumerable

            var ints = new[] {1, 2, 3, 4, 5};

            IEnumerable<int> intsGreaterThanOne = ints.Where(x => x > 1);
            IEnumerable<int> intsGreaterThanTwo = intsGreaterThanOne.Where(x => x > 2);
            Assert.AreEqual(3, intsGreaterThanTwo.Count());
            Assert.AreEqual(4, intsGreaterThanOne.Count());
            Assert.AreEqual(5, ints.Count());

            // linq queries are composable

            bool predicateWasCalled = false;
            intsGreaterThanOne = ints.Where(x =>
            {
                predicateWasCalled = true;
                return x > 1;
            });
            Assert.IsFalse(predicateWasCalled);
            Assert.AreEqual(4, intsGreaterThanOne.Count());
            Assert.IsTrue(predicateWasCalled);

            // deferred execution
        }

        // ~ 10-15 minutes

        [TestMethod]
        public void Demo2_paging_with_linq()
        {
            // paging is actually crazy easy in linq.
            // paging demonstrates both deferred execution and composable queries

            var ints = new[] {1, 2, 3, 4, 5, 6};
            IEnumerable<int> baseQuery = ints.Where(x => x > 0);

            int page = 2;
            int pageSize = 3;

            int total = baseQuery.Count();
            IEnumerable<int> pagedQuery = baseQuery.Skip((page - 1) * pageSize).Take(pageSize);

            Assert.AreEqual(6, total);
            Assert.AreEqual(3, pagedQuery.Count());
            Assert.AreEqual(3, new[] {4, 5, 6}.Union(pagedQuery).Count());
        }

        // ~ 5 minutes (~ 15-20 minutes total)

        [TestMethod]
        public void Demo3_projection()
        {
            string[] names = Student.Students
                .Select(x => string.Format("{0}, {1}", x.Last, x.First))
                .ToArray();

            Assert.AreEqual(12, names.Count());
            Assert.AreEqual("Omelchenko, Svetlana", names[0]);

            // simple projection

            var students = Student.Students
                .Select(x => new
                    {
                        x.Id,
                        FullName = string.Format("{0}, {1}", x.Last, x.First),
                        x.Scores
                    });

            Assert.AreEqual(12, students.Count());
            Assert.AreEqual("Omelchenko, Svetlana", students.First().FullName);

            // projecting into a DTO (anonymous object in this case)
        }

        // ~ 5 minutes (~ 20 - 25 minutes total)

        // Q/A time about LINQ in general

        [TestMethod]
        public void Demo4_extension_methods()
        {
            int count = 0;
            Student.Students.Each(x => count++);
            Assert.AreEqual(12, count);

            string[] names = Student.Students.Select(x => "{0}, {1}".F(x.Last, x.First)).ToArray();
            Assert.AreEqual(12, names.Count());
            Assert.AreEqual("Omelchenko, Svetlana", names[0]);
        }
    }
}